//  [10/18/2013 OMEGA] created

#include "DuelECCommon.h"
#include <QSet>
#include <QtAlgorithms>
#include "DuelECSelectable.h"
#include "DuelECSelectionMask.h"
#include "DuelECSelectionModel.h"

namespace DuelEC
{
	DECSelectionModel::DECSelectionModel()
	{

	}

	DECSelectionModel::~DECSelectionModel()
	{

	}

	void DECSelectionModel::setSelectionMask( DECSelectionMask mask )
	{
		mSelectionMask = mask;	
	}

	DECSelectionMask DECSelectionModel::getSelectionMask()
	{
		return mSelectionMask;
	}

	void DECSelectionModel::select( const SelectionList& list )
	{
		mergeList(list, LA_ReplaceList);
	}


	void DECSelectionModel::mergeList( const SelectionList& list, ListAdjustment adjMethod )
	{
		SelectionList uniqueList;
		removeDuplicated(list, uniqueList);
		SelectionList resultList;
		filterListImpl(uniqueList, resultList);
		switch (adjMethod)
		{
		case DuelEC::DECSelectionModel::LA_ReplaceList:
			mSelectedObjs = resultList;
			break;
		case DuelEC::DECSelectionModel::LA_XORWithList:
			{
				foreach(DECSelectable* itm, resultList)
				{
					bool existed = false;
					for (int i = 0; i < mSelectedObjs.size(); ++i)
					{
						if (mSelectedObjs.at(i) == itm)
						{
							mSelectedObjs.takeAt(i);
							existed = true;
							break;
						}
					}
					if (!existed)
					{
						// because items in resultList are unique, so we just add them
						// to the selected list.
						mSelectedObjs.push_back(itm);
					}
				}
			}
			break;
		case DuelEC::DECSelectionModel::LA_AddToList:
			{
				// ensure there is no duplication.
				foreach(DECSelectable* itm, resultList)
				{
					SelectionList::const_iterator i = qFind(mSelectedObjs, itm);
					if (i == mSelectedObjs.end())
					{
						mSelectedObjs.push_back(itm);
					}
				}
			}
			break;
		case DuelEC::DECSelectionModel::LA_RemoveFromList:
			{
				foreach(DECSelectable* itm, resultList)
				{
					SelectionList::iterator i = qFind(mSelectedObjs.begin(), mSelectedObjs.end(), itm);
					if (i != mSelectedObjs.end())
					{
						mSelectedObjs.erase(i);
					}
				}
			}
			break;
		case DuelEC::DECSelectionModel::LA_AddToHeadOfList:
			{
				SelectionList addingList;
				// ensure there is no duplication.
				foreach(DECSelectable* itm, resultList)
				{
					SelectionList::const_iterator i = qFind(mSelectedObjs, itm);
					if (i != mSelectedObjs.end())
					{
						addingList.push_back(itm);
					}
				}
				foreach(DECSelectable* itm, addingList)
				{
					mSelectedObjs.prepend(itm);
				}
			}
			break;
		default:
			break;
		}
	}

	void DECSelectionModel::clearList()
	{
		mSelectedObjs.clear();
	}


	void DECSelectionModel::filterListImpl( const SelectionList& list, SelectionList& outList )
	{
		outList.clear();
		foreach(DECSelectable* item, list)
		{
			if (mSelectionMask.queryEnabled(item->getTypeID()))
			{
				outList.push_back(item);
			}
		}
	}

	void DECSelectionModel::removeDuplicated( const SelectionList& list, SelectionList& outList )
	{
		QSet<DECSelectable*> selectionSet;
		outList.clear();
		foreach( DECSelectable* item, list )
		{
			selectionSet.insert(item);
		}

		QSet<DECSelectable*>::Iterator i;
		foreach( DECSelectable* item, list )
		{
			i = selectionSet.find(item);
			if ( i != selectionSet.end() )
			{
				outList.push_back(item);
				selectionSet.erase(i);
			}
		}

	}

}
